package handlers

import (
	"errors"
	"net/http"
	"strconv"
	"task_queue/internal/models"
	"task_queue/internal/plugin/mq"
	"task_queue/internal/response" // 确保导入了 response 包

	"github.com/gin-gonic/gin"
	"github.com/jinzhu/copier"
	"gorm.io/datatypes"
	"gorm.io/gorm"
)

type MQConfigHandler struct {
	DB        *gorm.DB
	mqPlugins map[mq.MQType]mq.MQPlugin
}

func NewMQConfigHandler(db *gorm.DB, mqPlugins map[mq.MQType]mq.MQPlugin) *MQConfigHandler {
	return &MQConfigHandler{
		DB:        db,
		mqPlugins: mqPlugins,
	}
}

// CreateMQConfig godoc
// @Summary 创建新的 MQ 配置
// @Description 添加一个新的消息队列配置项
// @Tags MQ Configs
// @Accept  json
// @Produce  json
// @Param   config body models.ReqMQConfig true "MQ 配置信息"
// @Success 200 {object} response.Response{data=models.MQConfig} "成功响应，返回创建的配置"
// @Failure 400 {object} response.Response "请求数据无效"
// @Failure 409 {object} response.Response "插件类型已存在冲突"
// @Failure 500 {object} response.Response "服务器内部错误"
// @Router /api/v1/mq-configs [post]
func (h *MQConfigHandler) CreateMQConfig(c *gin.Context) {
	var req models.ReqMQConfig
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Fail(c, http.StatusBadRequest, "无效的请求数据: "+err.Error())
		return
	}

	var mqConfig models.MQConfig
	// 使用 copier 复制基础字段
	if err := copier.Copy(&mqConfig, &req); err != nil {
		response.Fail(c, http.StatusInternalServerError, "复制请求数据失败: "+err.Error())
		return
	}

	// 单独处理 JSON 和指针字段
	mqConfig.ExtraConfig = datatypes.JSON(req.ExtraConfig) // 转换 RawMessage 到 datatypes.JSON
	if req.IsActive != nil {
		mqConfig.IsActive = *req.IsActive
	} else {
		mqConfig.IsActive = true // 默认激活
	}

	// 创建记录
	result := h.DB.Create(&mqConfig)
	if result.Error != nil {
		// 可以更具体地处理数据库错误，例如唯一约束冲突
		response.Fail(c, http.StatusInternalServerError, "创建 MQ 配置失败: "+result.Error.Error())
		return
	}

	response.Success(c, mqConfig)
}

// GetMQConfig godoc
// @Summary 获取单个 MQ 配置
// @Description 通过 ID 获取指定的消息队列配置信息
// @Tags MQ Configs
// @Produce  json
// @Param   id path uint true "MQ 配置 ID" Format(uint)
// @Success 200 {object} response.Response{data=models.MQConfig} "成功响应，返回查询到的配置"
// @Failure 400 {object} response.Response "无效的 ID 格式"
// @Failure 404 {object} response.Response "MQ 配置未找到"
// @Failure 500 {object} response.Response "服务器内部错误"
// @Router /api/v1/mq-configs/{id} [get]
func (h *MQConfigHandler) GetMQConfig(c *gin.Context) {
	idStr := c.Param("id")
	id, err := strconv.ParseUint(idStr, 10, 32)
	if err != nil {
		response.Fail(c, http.StatusBadRequest, "无效的 ID 格式")
		return
	}

	var mqConfig models.MQConfig
	result := h.DB.First(&mqConfig, uint(id))

	if result.Error != nil {
		if errors.Is(result.Error, gorm.ErrRecordNotFound) {
			response.Fail(c, http.StatusNotFound, "MQ 配置未找到")
		} else {
			response.Fail(c, http.StatusInternalServerError, "查询 MQ 配置失败: "+result.Error.Error())
		}
		return
	}

	response.Success(c, mqConfig)
}

// ListMQConfigs godoc
// @Summary 获取 MQ 配置列表
// @Description 获取消息队列配置列表，支持分页和按插件类型过滤
// @Tags MQ Configs
// @Produce  json
// @Param   page query int false "页码" default(1) Format(int)
// @Param   pageSize query int false "每页数量" default(10) Format(int)
// @Param   plugin_type query string false "按插件类型过滤" Format(string)
// @Success 200 {object} response.Response{data=object{items=[]models.MQConfig, total=int64, page=int, pageSize=int}} "成功响应，返回配置列表和分页信息"
// @Failure 500 {object} response.Response "服务器内部错误"
// @Router /api/v1/mq-configs [get]
func (h *MQConfigHandler) ListMQConfigs(c *gin.Context) {
	var mqConfigs []models.MQConfig
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "10"))
	pluginType := c.Query("plugin_type") // 获取过滤参数

	if page < 1 {
		page = 1
	}
	if pageSize < 1 {
		pageSize = 10
	}
	offset := (page - 1) * pageSize

	query := h.DB.Model(&models.MQConfig{})

	// 添加过滤条件
	if pluginType != "" {
		query = query.Where("plugin_type = ?", pluginType)
	}

	// 查询分页数据
	result := query.Offset(offset).Limit(pageSize).Find(&mqConfigs)
	if result.Error != nil {
		response.Fail(c, http.StatusInternalServerError, "查询 MQ 配置列表失败: "+result.Error.Error())
		return
	}

	// 查询总数 (应用相同的过滤条件)
	var total int64
	countQuery := h.DB.Model(&models.MQConfig{})
	if pluginType != "" {
		countQuery = countQuery.Where("plugin_type = ?", pluginType)
	}
	countResult := countQuery.Count(&total)
	if countResult.Error != nil {
		response.Fail(c, http.StatusInternalServerError, "查询总数失败: "+countResult.Error.Error())
		return
	}

	response.Success(c, gin.H{
		"items":    mqConfigs,
		"total":    total,
		"page":     page,
		"pageSize": pageSize,
	})
}

// UpdateMQConfig godoc
// @Summary 更新 MQ 配置信息
// @Description 更新指定 ID 的消息队列配置信息，不允许修改 PluginType
// @Tags MQ Configs
// @Accept  json
// @Produce  json
// @Param   id path uint true "MQ 配置 ID" Format(uint)
// @Param   config body models.ReqMQConfig true "要更新的 MQ 配置信息 (PluginType 字段将被忽略)"
// @Success 200 {object} response.Response{data=models.MQConfig} "成功响应，返回更新后的配置"
// @Failure 400 {object} response.Response "无效的 ID 格式或请求数据无效，或尝试修改 PluginType"
// @Failure 404 {object} response.Response "MQ 配置未找到"
// @Failure 500 {object} response.Response "服务器内部错误"
// @Router /api/v1/mq-configs/{id} [put]
func (h *MQConfigHandler) UpdateMQConfig(c *gin.Context) {
	idStr := c.Param("id")
	id, err := strconv.ParseUint(idStr, 10, 32)
	if err != nil {
		response.Fail(c, http.StatusBadRequest, "无效的 ID 格式")
		return
	}

	var existingMQConfig models.MQConfig
	findResult := h.DB.First(&existingMQConfig, uint(id))
	if findResult.Error != nil {
		if errors.Is(findResult.Error, gorm.ErrRecordNotFound) {
			response.Fail(c, http.StatusNotFound, "MQ 配置未找到")
		} else {
			response.Fail(c, http.StatusInternalServerError, "查询 MQ 配置失败: "+findResult.Error.Error())
		}
		return
	}

	var req models.ReqMQConfig
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Fail(c, http.StatusBadRequest, "无效的请求数据: "+err.Error())
		return
	}

	// 不允许通过此接口修改 PluginType
	if req.PluginType != "" && req.PluginType != existingMQConfig.PluginType {
		response.Fail(c, http.StatusBadRequest, "不允许修改插件类型 (PluginType)")
		return
	}

	// 使用 map 来更新，以便处理零值和 JSON
	updateData := map[string]interface{}{}
	if req.BrokerURLs != "" {
		updateData["broker_urls"] = req.BrokerURLs
	}
	// GroupName 可以为空字符串
	updateData["group_name"] = req.GroupName
	if req.ExtraConfig != nil {
		updateData["extra_config"] = datatypes.JSON(req.ExtraConfig)
	}
	if req.IsActive != nil {
		updateData["is_active"] = *req.IsActive
	}
	// Description 可以为空字符串
	updateData["description"] = req.Description

	// 使用 Updates 更新指定字段
	updateResult := h.DB.Model(&existingMQConfig).Updates(updateData)
	if updateResult.Error != nil {
		response.Fail(c, http.StatusInternalServerError, "更新 MQ 配置失败: "+updateResult.Error.Error())
		return
	}

	// 重新查询以返回最新数据（因为 Updates 不会更新所有关联）
	h.DB.First(&existingMQConfig, uint(id))
	response.Success(c, existingMQConfig)
}

// DeleteMQConfig godoc
// @Summary 删除 MQ 配置
// @Description 通过 ID 删除指定的消息队列配置 (软删除)
// @Tags MQ Configs
// @Produce  json
// @Param   id path uint true "MQ 配置 ID" Format(uint)
// @Success 200 {object} response.Response{data=object{message=string}} "成功响应，返回删除成功的消息"
// @Failure 400 {object} response.Response "无效的 ID 格式"
// @Failure 404 {object} response.Response "MQ 配置未找到"
// @Failure 500 {object} response.Response "服务器内部错误"
// @Router /api/v1/mq-configs/{id} [delete]
func (h *MQConfigHandler) DeleteMQConfig(c *gin.Context) {
	idStr := c.Param("id")
	id, err := strconv.ParseUint(idStr, 10, 32)
	if err != nil {
		response.Fail(c, http.StatusBadRequest, "无效的 ID 格式")
		return
	}

	// 先查找记录，以便返回被删除的对象（可选）
	var mqConfigToDelete models.MQConfig
	findResult := h.DB.First(&mqConfigToDelete, uint(id))
	if findResult.Error != nil {
		if errors.Is(findResult.Error, gorm.ErrRecordNotFound) {
			response.Fail(c, http.StatusNotFound, "MQ 配置未找到")
		} else {
			response.Fail(c, http.StatusInternalServerError, "查询 MQ 配置失败: "+findResult.Error.Error())
		}
		return
	}

	// 执行删除操作 (GORM 默认软删除)
	result := h.DB.Delete(&models.MQConfig{}, uint(id))
	if result.Error != nil {
		response.Fail(c, http.StatusInternalServerError, "删除 MQ 配置失败: "+result.Error.Error())
		return
	}

	if result.RowsAffected == 0 {
		// 理论上不应该发生，因为前面已经查到了
		response.Fail(c, http.StatusNotFound, "MQ 配置未找到或已被删除")
		return
	}

	response.Success(c, mqConfigToDelete) // 返回消息
}
